package tuanda.soict.firstsun.LogicPackage;

import java.util.ArrayList;

import tuanda.soict.firstsun.AbilityPackage.Ability;
import tuanda.soict.firstsun.AbilityPackage.Attack;
import tuanda.soict.firstsun.AbilityPackage.Occupy;
import tuanda.soict.firstsun.DataPackage.AttributeList;
import tuanda.soict.firstsun.DataPackage.CommonConstants;
import tuanda.soict.firstsun.EffectPackage.Effect;

/**
 * @author tuanda_soict_hut
 * @version 0.0.6
 * @since 7-10-2012
 */
public class Army extends Unit implements CommonConstants, AttributeList {

	private int level;
	private int health;
	private int experience;
	private int maxExp;
	private int armyID;
	private float killGold;
	private Ability attack_ability;
	private Ability occupy_ability;
	private int attribute;
	private ArrayList<Effect> effectList;
	private Ability[] abilityList;

	public Army(String nam, int id, int groID, int ran, int minAtk, int maxAtk,
			int def, int mov, int range, int typ, int gold, int x, int y,
			int dataID, Ability[] ability, int attr) {

		super(nam, groID, ran, minAtk, maxAtk, def, mov, range, typ, gold, x,
				y, dataID);
		setLevel(0);
		setInitialExperience(0);
		setHealth(DEFAULT_UNIT_HEALTH);
		setMaxExp(DEFAULT_ARMY_EXP_NEED_TO_UP);
		setKillGold(DEFAULT_ARMY_KILL_GOLD_RATE);
		setID(id);
		setAttribute(attr);
		attack_ability = new Attack(0, "Attack", this.getTotalAttackRange(), 1,
				AFFECT_ENEMY);
		occupy_ability = new Occupy(2, "Occupy", 0, 1, AFFECT_ENEMY);
		effectList = new ArrayList<Effect>();
		setAbility(ability);
	}

	public final int getHealth() {
		return this.health;
	}

	public final void setHealth(int hp, ArmyManager manager,
			boolean isCalculation) {
		if (hp <= 0) {
			this.health = 0;
			if (isCalculation == false) {
				manager.addDeadArmyItem(this);
			}
		} else if (hp > DEFAULT_UNIT_HEALTH) {
			this.health = DEFAULT_UNIT_HEALTH;
		} else {
			this.health = hp;
		}
	}

	public final void setHealth(int hp) {
		if (hp <= 0) {
			this.health = 0;
		} else if (hp > DEFAULT_UNIT_HEALTH) {
			this.health = DEFAULT_UNIT_HEALTH;
		} else {
			this.health = hp;
		}
	}

	public final boolean isDead() {
		if (getHealth() == 0) {
			return true;
		} else {
			return false;
		}
	}

	public final int getLevel() {
		return this.level;
	}

	public final void setLevel(int lev) {
		if (lev > -1 && level < 10) {
			this.level = lev;
		}
	}

	public final int getExperience() {
		return this.experience;
	}

	public final void setInitialExperience(int exp) {
		this.experience = exp;
	}

	public final void setExperience(int exp, ArmyManager levelUpManager) {
		if (exp >= 0 && exp < maxExp) {
			this.experience = exp;
		} else if (exp >= maxExp) {
			int levelUp = exp / maxExp;
			this.experience = exp % maxExp;
			int total = getLevel() + levelUp;
			if (total < 10) {
				setLevel(total);
				setAttack(
						getMinAttack() + DEFAULT_ARMY_MIN_ATTACK_UP * levelUp,
						getMaxAttack() + DEFAULT_ARMY_MAX_ATTACK_UP * levelUp);
				this.setDefense(this.getDefense() + DEFAULT_ARMY_DEFENSE_UP
						* levelUp);
				this.setRank(getRank() + DEFAULT_ARMY_RANK_UP * levelUp);
			} else {
				setLevel(9);
				levelUp = 9 - getLevel();
				setAttack(
						getMinAttack() + DEFAULT_ARMY_MIN_ATTACK_UP * levelUp,
						getMaxAttack() + DEFAULT_ARMY_MAX_ATTACK_UP * levelUp);
				this.setDefense(this.getDefense() + DEFAULT_ARMY_DEFENSE_UP
						* levelUp);
				this.setRank(getRank() + DEFAULT_ARMY_RANK_UP * levelUp);
			}
			if (levelUp > 0) {
				levelUpManager.addLevelUpArmyItem(this);
			}
		}
	}

	@Override
	public final int getID() {
		return this.armyID;
	}

	@Override
	public final void setID(int id) {
		this.armyID = id;
	}

	public final Ability getAttackAbility() {
		return this.attack_ability;
	}

	public final void setAttackAbility(Ability abil) {
		this.attack_ability = abil;
	}

	public final Ability getOccupyAbility() {
		return this.occupy_ability;
	}

	public final void setOccupyAbility(Ability abil) {
		this.occupy_ability = abil;
	}

	public final int getMaxExp() {
		return maxExp;
	}

	public final void setMaxExp(int max) {
		this.maxExp = max;
	}

	public final float getKillGold() {
		return killGold;
	}

	public final void setKillGold(float gold) {
		this.killGold = gold;
	}

	public final int getAttribute() {
		return attribute;
	}

	public final void setAttribute(int attribute) {
		this.attribute = attribute;
		switch (attribute) {
		case WATER_ATTRIBUTE:
			setMaxExp(getMaxExp() - 3000);
			break;
		case FIRE_ATTRIBUTE:
			setAttack(this.getMinAttack() + 5, this.getMaxAttack() + 5);
			break;
		case AIR_ATTRIBUTE:
			setMovement(this.getMovement() + 1);
			break;
		case EARTH_ATTRIBUTE:
			setDefense(this.getDefense() + 5);
			break;
		case LIGHT_ATTRIBUTE:
			setInitialExperience((int) (0.7 * DEFAULT_ARMY_EXP_NEED_TO_UP));
			break;
		case DARK_ATTRIBUTE:
			setKillGold(0.4f);
			break;
		}
	}

	public final void decreaseEffectDuration() {
		Effect temp;
		for (int i = 0; i < effectList.size(); i++) {
			temp = effectList.get(i);
			if (temp.getEffectDuration() > 0) {
				temp.setEffectDuration(temp.getEffectDuration() - 1);
				temp.mainAct(this);
			} else if (temp.getEffectDuration() == 0) {
				temp.afterAct(this);
				effectList.remove(i);
				i--;
			}
		}
	}

	public final ArrayList<Effect> getEffectList() {
		return this.effectList;
	}

	public final void addEffect(Effect eff) {
		this.effectList.add(eff);
		eff.beforeAct(this);
	}

	public final void removeEffectAtIndex(int index) {
		Effect temp;
		if (index > -1 && index < effectList.size()) {
			temp = effectList.get(index);
			temp.afterAct(this);
			effectList.remove(index);
		}
	}

	public final void removeEffect(int id) {
		Effect temp;
		for (int i = 0; i < effectList.size(); i++) {
			temp = effectList.get(i);
			if (id == temp.getID()) {
				effectList.remove(i);
				temp.afterAct(this);
				i--;
			}
		}
	}

	public final Ability getSkill(int index) {
		if (index > -1 && index < abilityList.length) {
			return this.abilityList[index];
		} else {
			return null;
		}
	}

	public final Ability[] getAbility(int level) {
		if (level < 2) {
			Ability[] temp = { abilityList[0] };
			return temp;
		} else if (level < 4) {
			Ability[] temp = { abilityList[0], abilityList[1] };
			return temp;
		} else if (level < 6) {
			Ability[] temp = { abilityList[0], abilityList[1], abilityList[2] };
			return temp;
		} else {
			return abilityList;
		}
	}

	public final void setAbility(Ability[] abil) {
		this.abilityList = abil;
	}

}
